<?php
namespace Fox;

class Template {

	private $cache_path = '';
	private $xss_filter = '';
	private $view_path = '';
	private $ext =  '';
	private $compiler_finish = false;

	public function __construct($pars){

		$this->view_path = $pars['view_path'];
		$this->cache_path = combine_paths($this->view_path,$pars['cache_dir']);	
		$this->xss_filter = $pars['xss_filter'];
		$this->ext = $pars['ext'];
		$this->compiler_finish = $pars['compiler_finish'];
		if (!$this->compiler_finish && !is_dir($this->cache_path)) {
			mkdir($this->cache_path);
		}
	}

	public function include($path) {
		$path =$path.$this->ext;
		$this->base_path = dirname($path);
		$view = strtolower($path);
		$cache_file_name = trim(str_replace(['\\', '/', ':_'], '_', $view), '.');
		$cache_file_path = combine_paths($this->cache_path, $cache_file_name);

		if(!$this->compiler_finish){
			if (!is_file($cache_file_path) || filemtime($cache_file_path) < filemtime($path)) {
				file_put_contents($cache_file_path, $this->compiler(file_get_contents($path)));
			}
		}
		
		$path = $cache_file_path;
		extract(ViewData::All());
		include $path;
	}

	private $base_path;

	/**
	 * 引入视图文件
	 */
	 
	public function incChild($path) {
		$path = combine_paths($this->base_path, $path);
		$this->include($path);
	}

	private  function echoVal($match) {

		$first = substr($match[0], 0, 1);
		if ($first == '\\') {
			return '@' . $match[1];
		}

		$all = $match[1];
		$parts = explode('|', $all);
		$ret = $parts[0];
		$ret = preg_replace('/\.([\w\s]+)/', '[\'$1\']', $ret);
		$ret = preg_replace('/:([\w\s]+)/', '->$1', $ret);
		$ret = '$' . $ret;

		array_shift($parts);
		$parts[] = $this->xss_filter;

		$len = count($parts);
		for ($i = 0; $i < $len; $i++) {
			$item = $parts[$i];
			if ($item == 'END') {
				break;
			} else {
				$ret = "$item($ret)";
			}
		}
		return '<?php echo ' . $ret . '; ?>';
	}

	/**
	 * 编译模板
	 * @param $tpl 模板内容
	 * @return mixed 返回编译后的php内容
	 */
	private function compiler($tpl) {

		$tokens = [
			'/@(if)(\s*\(.*\))/' => '<?php $1$2 { ?>',
			'/@(elseif)(\s*\(.*\))/' => '<?php }$1$2 { ?>',
			'/@(else)/' => '<?php } $1 { ?>',
			'/@(while|foreach|for)(\s*\(.*\))/' => '<?php $__i__=0;$1$2 { $__i__+=1;?>',
			'/@(empty)/' => '<?php } if($__i__ === 0){ ?>',
			'/@(endforeach|endfor|endif|endwhile|end)/' => '<?php } ?>',
			'/@(include)(\s*\(.*\))/' => '<?php $this->incChild$2 ; ?>',
			'/@(break|continue)(\s*\(.*\))/' => '<?php if $2 { $1 ;} ?>',
			'/@\{\{(.+?)\}\}/' => '<?php echo $1; ?>',
			'/!@\{(.+?)\}/' => '<?php $1; ?>',
		];

		$tpl = preg_replace(array_keys($tokens), array_values($tokens), $tpl);
		$tpl = preg_replace_callback('/\\\\?@\{(.+?)\}/',  [$this,'echoVal'], $tpl);
		$tpl = preg_replace_callback('/\\\\?@([\w\.:\(\)\|]+)/', [$this,'echoVal'], $tpl);
		return $tpl;
	}
}
